package cn.xopencode.userservice.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.xopencode.common.framework.vo.CommonResult;
import cn.xopencode.common.framework.vo.PageResult;
import cn.xopencode.mybatis.core.query.QueryWrapperX;
import cn.xopencode.oss.rpc.permission.PositionRpc;
import cn.xopencode.oss.rpc.permission.vo.PositionVO;
import cn.xopencode.userservice.convert.UserConvert;
import cn.xopencode.userservice.dal.mysql.dataobject.UserDO;
import cn.xopencode.userservice.dal.mysql.mapper.UserMapper;
import cn.xopencode.userservice.rpc.user.dto.*;
import cn.xopencode.userservice.util.FunUtil;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @DubboReference(version = "${dubbo.consumer.PositionRpc.version}", validation = "false")
    private PositionRpc positionRpc;

    public UserDTO getUser(String userId) {
        UserDTO userDTO = null;
        UserDO userDO = userMapper.selectById(userId);
        if (null != userDO) {
            userDTO = UserConvert.INSTANCE.convert(userDO);
        }
        return userDTO;
    }

    public List<UserDTO> getUserList(String userId) {
        UserDO userDO = userMapper.selectById(userId);
        List<UserDO> userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().eq("dept_id", userDO.getDeptId()));
        return UserConvert.INSTANCE.convert(userDOList);
    }

    public List<UserDTO> getUserList(UserParamDTO userParamDTO) {
        List<UserDO> userDOList = null;
        if (StrUtil.isNotBlank(userParamDTO.getDeptId())) {
            userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().eq("dept_id", userParamDTO.getDeptId()));
        } else if (StrUtil.isNotBlank(userParamDTO.getEmplName())) {
            userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().like("empl_name", SqlUtils.concatLike(userParamDTO.getEmplName(), SqlLike.DEFAULT)));
        } else if (StrUtil.isNotBlank(userParamDTO.getPositionId())) {
            userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().eq("position_id", userParamDTO.getPositionId()));
        } else if (StrUtil.isNotBlank(userParamDTO.getUserName()) && StrUtil.isNotBlank(userParamDTO.getPassword())) {
            userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().eq("user_name", userParamDTO.getUserName()).eq("password", userParamDTO.getPassword()));
            setLoginIpDate(userParamDTO, userDOList);
        } else if (StrUtil.isNotBlank(userParamDTO.getMobile()) && StrUtil.isNotBlank(userParamDTO.getPassword())) {
            userDOList = userMapper.selectList(new QueryWrapperX<UserDO>().eq("mobile", userParamDTO.getMobile()).eq("password", userParamDTO.getPassword()));
            setLoginIpDate(userParamDTO, userDOList);
        }
        return UserConvert.INSTANCE.convert(userDOList);
    }

    private void setLoginIpDate(UserParamDTO userParamDTO, List<UserDO> userDOList) {
        if (CollUtil.isNotEmpty(userDOList)) {
            userDOList.forEach(userDO -> {
                userDO.setLoginIp(userParamDTO.getLoginIp());
                userDO.setLoginDate(userParamDTO.getLoginDate());
                userMapper.updateById(userDO);
            });
        }
    }

    public String getEmployeeName(String userIds) {
        List<UserDO> userDOList = userMapper.selectBatchIds(new ArrayList<>(Arrays.asList(userIds.split(","))));
        List<String> list = userDOList.stream().map(UserDO::getEmplName).collect(Collectors.toList());
        return String.join(",", list);
    }

    public String CreateUser(CreateUserDTO createUserDTO) {
        UserDO userDO = UserConvert.INSTANCE.convert(createUserDTO);
        userDO.setId(IdUtil.objectId());
        FunUtil.defaultValue(userDO, createUserDTO.getUserId(), true);
        if (StrUtil.isBlank(userDO.getPassword())) {
            userDO.setPassword(StrUtil.reverse(StrUtil.reverse(userDO.getMobile()).substring(0, 6)));
        }
        userDO.setStatus(1);
        userDO.setIsDeleted(1);
        userMapper.insert(userDO);
        return userDO.getId();
    }

    public PageResult<UserDTO> findUserList(UserPageDTO userPageDTO) {
        if (StrUtil.isNotBlank(userPageDTO.getVague())) {
            userPageDTO.setVague(SqlUtils.concatLike(userPageDTO.getVague(), SqlLike.DEFAULT));
        }
        Page<UserDTO> userDTOList = userMapper.findUserList(new Page<UserDTO>(userPageDTO.getPageNo(), userPageDTO.getPageSize()), userPageDTO);
        List<String> positionIdList = userDTOList.getRecords().stream().map(UserDTO::getPositionId).collect(Collectors.toList());
        CommonResult<List<PositionVO>> commonResult = positionRpc.listPositions(positionIdList);
        Map<String, String> postMap = commonResult.getData().stream().collect(Collectors.toMap(PositionVO::getId, PositionVO::getPostName));
        userDTOList.getRecords().forEach(userDTO -> {
            if (postMap.containsKey(userDTO.getPositionId())) {
                userDTO.setPositionName(postMap.get(userDTO.getPositionId()));
            }
        });
        PageResult<UserDTO> pageResult = new PageResult().setList(userDTOList.getRecords()).setTotal(userDTOList.getTotal());
        return pageResult;
    }

    public Integer updateUser(List<UpdateUserDTO> updateUserDTOList) {
        Integer count = 0;
        for (UpdateUserDTO updateUserDTO : updateUserDTOList) {
            UserDO userDO = UserConvert.INSTANCE.convert(updateUserDTO);
            FunUtil.defaultValue(userDO, updateUserDTO.getUserId(), false);
            count += userMapper.updateById(userDO);
        }
        return count;
    }

    public Integer updateProperty(List<UpdatePropertyDTO> updatePropertyDTOList) {
        Integer count = 0;
        for (UpdatePropertyDTO updatePropertyDTO : updatePropertyDTOList) {
            if (FunUtil.mustOne(updatePropertyDTO.getPositionId(), updatePropertyDTO.getDeptId(), updatePropertyDTO.getStatus(), updatePropertyDTO.getIsDeleted()))
                count += userMapper.updateById(new UserDO() {{
                    setId(updatePropertyDTO.getId());
                    if (StrUtil.isNotBlank(updatePropertyDTO.getPositionId()))
                        setPositionId(updatePropertyDTO.getPositionId());
                    if (StrUtil.isNotBlank(updatePropertyDTO.getDeptId()))
                        setDeptId(updatePropertyDTO.getDeptId());
                    if (StrUtil.isNotBlank(updatePropertyDTO.getStatus()))
                        setStatus(Integer.valueOf(updatePropertyDTO.getStatus()));
                    if (StrUtil.isNotBlank(updatePropertyDTO.getIsDeleted()))
                        setIsDeleted(Integer.valueOf(updatePropertyDTO.getIsDeleted()));
                    FunUtil.defaultValue(this, updatePropertyDTO.getUserId(), false);
                }});
        }
        return count;
    }

    public UserDTO createUserIfAbsent(CreateUserDTO createUserDTO) {
        UserDO userDO;
        userDO = userMapper.selectOne(new QueryWrapperX<UserDO>().eq("mobile", createUserDTO.getMobile()));
        if (null == userDO) {
            String id = CreateUser(createUserDTO);
            userDO = userMapper.selectById(id);
        }
        return UserConvert.INSTANCE.convert(userDO);
    }
}
